import React, { useEffect, useRef, useState } from 'react';
import { Image } from 'antd';
import styles from './index.module.css';

interface CardItem {
  id: string;
  imageUrl: string;
  height: number;
  width: number;
}

// 生成更丰富的测试数据
const generateTestData = (count: number): CardItem[] => {
  const aspectRatios = [0.75, 1, 1.33, 1.5, 1.77, 2, 2.35]; // 多种宽高比
  return Array.from({ length: count }, (_, index) => {
    const ratio = aspectRatios[Math.floor(Math.random() * aspectRatios.length)];
    const width = 800 + Math.floor(Math.random() * 400);
    const height = width / ratio;
    return {
      id: `item-${index}`,
      imageUrl: `https://picsum.photos/${Math.floor(width)}/${Math.floor(height)}?random=${index}`,
      width,
      height,
    };
  });
};

interface VirtualWaterfallProps {
  data?: CardItem[];
  columnCount?: number;
  columnGap?: number;
  rowGap?: number;
}

const VirtualWaterfall: React.FC<VirtualWaterfallProps> = ({
  data = generateTestData(500), // 默认生成500张图片
  columnCount = 6,
  columnGap = 16,
  rowGap = 16,
}) => {
  const containerRef = useRef<HTMLDivElement>(null);
  const [visibleItems, setVisibleItems] = useState<CardItem[]>([]);
  const [containerWidth, setContainerWidth] = useState(0);
  const [scrollTop, setScrollTop] = useState(0);
  const columnHeights = useRef<number[]>(new Array(columnCount).fill(0));
  const itemPositions = useRef<Map<string, { top: number; left: number; column: number }>>(new Map());

  // 计算每列的宽度
  const columnWidth = containerWidth ? (containerWidth - (columnCount - 1) * columnGap) / columnCount : 0;

  // 计算图片的理想高度 - 增加更多随机性
  const calculateIdealHeight = (item: CardItem): number => {
    const baseHeight = columnWidth / (item.width / item.height);
    
    // 添加随机变化，使高度更丰富
    const randomFactor = 0.8 + Math.random() * 0.4; // 0.8-1.2之间的随机因子
    const randomizedHeight = baseHeight * randomFactor;
    
    // 限制最小和最大高度
    const minHeight = columnWidth * 0.6;
    const maxHeight = columnWidth * 3;
    
    return Math.max(minHeight, Math.min(maxHeight, randomizedHeight));
  };

  // 计算每个项目的位置 - 改进算法
  const calculateItemPositions = () => {
    if (columnWidth <= 0) return;
    
    // 重置列高度
    columnHeights.current = new Array(columnCount).fill(0);
    itemPositions.current.clear();

    // 预计算所有图片的显示高度
    const scaledItems = data.map(item => ({
      ...item,
      scaledHeight: calculateIdealHeight(item)
    }));

    // 改进的布局算法：不完全按高度排序，增加随机性
    const sortedItems = [...scaledItems];
    // 随机打乱部分顺序，避免完全按高度排序
    for (let i = sortedItems.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [sortedItems[i], sortedItems[j]] = [sortedItems[j], sortedItems[i]];
    }

    // 放置图片
    sortedItems.forEach((item) => {
      // 找到最短的列
      let columnIndex = 0;
      let minHeight = columnHeights.current[0];
      
      // 随机选择最短的几列之一，增加变化
      const candidates = [];
      for (let i = 0; i < columnCount; i++) {
        if (columnHeights.current[i] < minHeight * 1.2) { // 允许一定误差
          candidates.push(i);
        }
      }
      
      if (candidates.length > 0) {
        columnIndex = candidates[Math.floor(Math.random() * candidates.length)];
      } else {
        columnIndex = columnHeights.current.indexOf(minHeight);
      }

      // 记录位置信息
      itemPositions.current.set(item.id, {
        top: columnHeights.current[columnIndex],
        left: columnIndex * (columnWidth + columnGap),
        column: columnIndex,
      });

      // 更新列高度
      columnHeights.current[columnIndex] += item.scaledHeight + rowGap;
    });
  };

  // 计算可视区域内的项目 - 增加缓冲区
  const calculateVisibleItems = () => {
    if (!containerRef.current) return;
    
    const containerHeight = window.innerHeight;
    const visibleItems: CardItem[] = [];
    const bufferHeight = 2000; // 更大的缓冲区

    data.forEach((item) => {
      const position = itemPositions.current.get(item.id);
      if (position) {
        const itemTop = position.top;
        const itemHeight = calculateIdealHeight(item);
        
        // 判断是否在可视区域内（包含缓冲区）
        if (
          itemTop + itemHeight > scrollTop - bufferHeight &&
          itemTop < scrollTop + containerHeight + bufferHeight
        ) {
          visibleItems.push(item);
        }
      }
    });

    setVisibleItems(visibleItems);
  };

  // 监听容器大小变化
  useEffect(() => {
    const observer = new ResizeObserver((entries) => {
      for (const entry of entries) {
        setContainerWidth(entry.contentRect.width);
      }
    });

    if (containerRef.current) {
      observer.observe(containerRef.current);
    }

    return () => observer.disconnect();
  }, []);

  // 监听滚动事件 - 增加节流
  useEffect(() => {
    let ticking = false;
    
    const handleScroll = () => {
      if (!ticking) {
        window.requestAnimationFrame(() => {
          setScrollTop(window.scrollY);
          ticking = false;
        });
        ticking = true;
      }
    };

    window.addEventListener('scroll', handleScroll);
    return () => window.removeEventListener('scroll', handleScroll);
  }, []);

  // 当容器宽度或数据变化时重新计算位置
  useEffect(() => {
    if (containerWidth > 0) {
      calculateItemPositions();
      calculateVisibleItems();
    }
  }, [containerWidth, data, columnCount, columnGap, rowGap]);

  // 当滚动位置变化时重新计算可视项目
  useEffect(() => {
    calculateVisibleItems();
  }, [scrollTop]);

  return (
    <div 
      ref={containerRef} 
      className={styles.container}
      style={{ 
        minHeight: Math.max(...columnHeights.current),
        padding: `0 ${columnGap}px`
      }}
    >
      {visibleItems.map((item) => {
        const position = itemPositions.current.get(item.id);
        if (!position) return null;

        const itemHeight = calculateIdealHeight(item);

        return (
          <div
            key={item.id}
            className={styles.item}
            style={{
              transform: `translate3d(${position.left}px, ${position.top}px, 0)`,
              width: columnWidth,
              height: itemHeight,
            }}
          >
            <div className={styles.card}>
              <Image
                src={item.imageUrl}
                alt=""
                preview={false}
                className={styles.image}
                loading="lazy"
              />
            </div>
          </div>
        );
      })}
    </div>
  );
};

export default VirtualWaterfall;